import { CardTypeRequestProxyFactory, CardUsingEventHandler, CardUsingEventWrapper, ResponseHandlerProxy } from "@/core/playersystem/handlers";
import { Card, CardType, Color, Equipment, HurtType } from "../card";
import { Sha, Shan } from "../basicCard";
import { Player } from "@/core/playersystem/player";
import { DefaultPromise } from "@/core/util/common";
import { createDefaultEvent, WaitForPushCardEvent } from "@/store/reactiveStore";
import { HuoGong, NanManRuQin, WanJianQiFa } from "../brilliantness/nodelay";


export class Shield extends Equipment {

    static areaIndex():number {
        return 1
    }
}

export class BaGuaZhen extends Shield {

    baguazhenProxyFactory: CardTypeRequestProxyFactory

    constructor(color: Color, number: number) {
        super(color, number)
        const baguazhenProxyFactory: CardTypeRequestProxyFactory = {
            name: 'baguazhenProxyFactory',
            createResponseHandlerProxy<T extends Card>(player: Player): ResponseHandlerProxy<T> {
                return {
                    shouldApply(extendsHandler: CardUsingEventHandler<T>): boolean {
                        const sourceCard = extendsHandler.card
                        // 目标是作用对象自己
                        const selfTarget = sourceCard.cardProperties.target != null && sourceCard.cardProperties.target.equals(player)
                        const equip = player.equipmentAreas.getShield()
                        const hasEquip = equip != null && equip instanceof BaGuaZhen
                        return selfTarget && hasEquip
                    },
                    apply(extendsHandler: CardUsingEventHandler<T>): CardUsingEventHandler<T> {
                        class BaGuaZhenEvent extends CardUsingEventWrapper<T> {
                            constructor(cardUsingEventHandler: CardUsingEventHandler<T>, player: Player) {
                                super(cardUsingEventHandler)
                                this.player = player
                            }

                            async needAndWaitForResponse<R extends Card>(requestCardType: CardType<R>): Promise<WaitForPushCardEvent> {
                                const res = this.cardUsingEventHandler.needAndWaitForResponse(requestCardType)
                                if (requestCardType.name == Shan.name && this.player) {
                                    // 请求需要出闪时使用
                                    const lastResult = await res
                                    if (lastResult.cancel) {
                                        const sourceCard = this.card
                                        const gm = this.player.gameManager
                                        const predicate = (judgeCard: Card):boolean => judgeCard.isRed()
                                        const judgeCard = await gm.launchJudge(this.player, this.card, predicate)
                                        if (judgeCard && predicate(judgeCard)) {
                                            const selectedCards = [judgeCard]
                                            gm.appendLog('八卦阵判定成功,判定结果为: ' + judgeCard.colorCN() + judgeCard.numberCN() + judgeCard.info())
                                            return createDefaultEvent({ selectedCards })
                                        } else {
                                            const info = judgeCard && judgeCard.colorCN() + judgeCard.numberCN() + judgeCard.info()
                                            gm.appendLog('八卦阵判定失败,判定结果为: ' + info)
                                        }
                                    }
                                }

                                return res
                            }
                        }

                        return new BaGuaZhenEvent(extendsHandler, player)
                    }
                }
            }
        }
        this.baguazhenProxyFactory = baguazhenProxyFactory
    }

    async use(): Promise<void> {
        super.use()
        if (this.cardProperties.owner) {
            this.cardProperties.owner.registerRequestCardProxy(this.baguazhenProxyFactory)
        }
    }

    onDrop(): void {
        if (this.cardProperties.owner && this.hasEquip()) {
            this.cardProperties.owner.removeRequestCardProxy(this.baguazhenProxyFactory)
        }

        super.onDrop()
    }

    info(): string {
        return "八卦阵"
    }

}

export class Baiyinshizi extends Shield {
    baiyinshiziProxyFactory: CardTypeRequestProxyFactory
    constructor(color: Color, number: number) {
        super(color, number)
        const baiyinshiziProxyFactory: CardTypeRequestProxyFactory = {
            name: 'baiyinshiziProxyFactory',
            createResponseHandlerProxy<T extends Card>(player: Player): ResponseHandlerProxy<T> {
                return {
                    shouldApply(extendsHandler: CardUsingEventHandler<T>): boolean {
                        const sourceCard = extendsHandler.card
                        // 目标是作用对象自己
                        const selfTarget = sourceCard.cardProperties.target != null && sourceCard.cardProperties.target.equals(player)
                        const equip = player.equipmentAreas.getShield()
                        const hasEquip = equip != null && equip instanceof Baiyinshizi
                        return selfTarget && hasEquip
                    },
                    apply(extendsHandler: CardUsingEventHandler<T>): CardUsingEventHandler<T> {

                        class BaiyinEvent extends CardUsingEventWrapper<T> {
                            constructor(cardUsingEventHandler: CardUsingEventHandler<T>, player: Player) {
                                super(cardUsingEventHandler)
                                this.player = player
                            }
                            async calHurt(): Promise<number> {
                                const res = this.cardUsingEventHandler.calHurt()
                                const hurtCount = await res
                                if (hurtCount > 1) {
                                    if (this.player) {
                                        const gm = this.player.gameManager
                                        gm.appendLog('白银狮子勇抵挡,伤害为1')
                                    }

                                    return DefaultPromise(1)
                                }
                                return res
                            }
                        }

                        return new BaiyinEvent(extendsHandler, player)
                    }
                }
            }
        }
        this.baiyinshiziProxyFactory = baiyinshiziProxyFactory
    }

    async use(): Promise<void> {
        super.use()
        if (this.cardProperties.owner) {
            this.cardProperties.owner.registerRequestCardProxy(this.baiyinshiziProxyFactory)
        }
        
    }

    onDrop(): void {
        if (this.cardProperties.owner && this.hasEquip()) {
            this.cardProperties.owner.removeRequestCardProxy(this.baiyinshiziProxyFactory)
            this.cardProperties.owner.recoverHP(1)
            this.cardProperties.owner.gameManager.appendLog('失去白银狮子,恢复1体力')
        }

        super.onDrop()
    }

    info(): string {
        return "白银狮子"
    }
}

export class Renwangdun extends Shield {

    renwangdunProxyFactory: CardTypeRequestProxyFactory

    constructor(color: Color, number: number) {
        super(color, number)

        const renwangdunProxyFactory: CardTypeRequestProxyFactory = {
            name: 'renwangdunProxyFactory',
            createResponseHandlerProxy<T extends Card>(player: Player): ResponseHandlerProxy<T> {
                return {
                    shouldApply(extendsHandler: CardUsingEventHandler<T>): boolean {
                        const sourceCard = extendsHandler.card
                        // 目标是作用对象自己
                        const selfTarget = sourceCard.cardProperties.target != null && sourceCard.cardProperties.target.equals(player)
                        const equip = player.equipmentAreas.getShield()
                        const hasEquip = equip != null && equip instanceof Renwangdun
                        // 使用的黑色杀
                        const blackSha = sourceCard instanceof Sha && sourceCard.isBlack()

                        return selfTarget && hasEquip && blackSha
                    },

                    apply(extendsHandler: CardUsingEventHandler<T>): CardUsingEventHandler<T> {
                        class RenwangdunEvent extends CardUsingEventWrapper<T> {
                            constructor(cardUsingEventHandler: CardUsingEventHandler<T>, player: Player) {
                                super(cardUsingEventHandler)
                                this.player = player
                            }
                            specTarget(): Promise<void> {
                                const res = this.cardUsingEventHandler.specTarget()
                                const sourceCard = this.card
                                sourceCard.cardProperties.cancelEffect = true
                                const player = sourceCard.cardProperties.target
                                if (player) {
                                    const gm = player.gameManager
                                    gm.appendLog(player.name + '使用仁王盾,黑色杀无效')
                                }
                                return res
                            }
                        }
                        return new RenwangdunEvent(extendsHandler, player)
                    }
                }
            }
        }

        this.renwangdunProxyFactory = renwangdunProxyFactory
    }

    async use(): Promise<void> {
        super.use()

        if (this.cardProperties.owner && this.hasEquip()) {
            this.cardProperties.owner.registerRequestCardProxy(this.renwangdunProxyFactory)
        }
    }

    onDrop(): void {
        if (this.cardProperties.owner) {
            this.cardProperties.owner.removeRequestCardProxy(this.renwangdunProxyFactory)
        }

        super.onDrop()
    }

    info(): string {
        return "仁王盾"
    }
}

export class Tengjia extends Shield {
    
    tengjiaProxyFactory: CardTypeRequestProxyFactory

    constructor(color: Color, number: number) {
        super(color, number)

        const tengjiaProxyFactory: CardTypeRequestProxyFactory = {
            name: 'tengjiaProxyFactory',
            createResponseHandlerProxy<T extends Card>(player: Player): ResponseHandlerProxy<T> {
                return {
                    shouldApply(extendsHandler: CardUsingEventHandler<T>): boolean {
                        const sourceCard = extendsHandler.card
                        // 目标是作用对象自己
                        const selfTarget = sourceCard.cardProperties.target != null && sourceCard.cardProperties.target.equals(player)
                        const equip = player.equipmentAreas.getShield()
                        // 是否有装备
                        const hasEquip = equip != null && equip instanceof Tengjia
                        // 普通杀 或 火杀
                        const normalOrFireSha = sourceCard instanceof Sha && (sourceCard.hurtType() == HurtType.NORMAL || sourceCard.hurtType() == HurtType.FIRE)
                        // 南蛮入侵/万剑齐发/火攻
                        const orhuogongNanmanWanjian = sourceCard instanceof HuoGong || sourceCard instanceof NanManRuQin || sourceCard instanceof WanJianQiFa
                        return selfTarget && hasEquip && (normalOrFireSha || orhuogongNanmanWanjian)
                    },
                    apply(extendsHandler: CardUsingEventHandler<T>): CardUsingEventHandler<T> {
                        class TengjiaEvent extends CardUsingEventWrapper<T> {
                            constructor(cardUsingEventHandler: CardUsingEventHandler<T>, player: Player) {
                                super(cardUsingEventHandler)
                                this.player = player
                            }

                            specTarget(): Promise<void> {
                                const res = this.cardUsingEventHandler.specTarget()
                                const sourceCard = this.card
                                if (sourceCard instanceof NanManRuQin || sourceCard instanceof WanJianQiFa || (sourceCard instanceof Sha && sourceCard.hurtType() == HurtType.NORMAL)) {
                                    sourceCard.cardProperties.cancelEffect = true
                                    if (this.player) {
                                        const gm = this.player.gameManager
                                        gm.appendLog(this.player.name + '使用了藤甲,抵挡普通杀/南蛮/万箭效果')
                                    }
                                }
                                return res
                            }

                            async calHurt(): Promise<number> {
                                const res = this.cardUsingEventHandler.calHurt()
                                const sourceCard = this.card
                                if (sourceCard.hurtType() == HurtType.FIRE) {
                                    const fireHurt = await res + 1
                                    return DefaultPromise(fireHurt)
                                }
                                return res
                            }
                        }
                        return new TengjiaEvent(extendsHandler, player)
                    }
                }
            }
        }
        this.tengjiaProxyFactory = tengjiaProxyFactory
    }

    async use(): Promise<void> {
        super.use()

        if (this.cardProperties.owner) {
            this.cardProperties.owner.registerRequestCardProxy(this.tengjiaProxyFactory)
        }
    }

    onDrop(): void {
        if (this.cardProperties.owner && this.hasEquip()) {
            this.cardProperties.owner.removeRequestCardProxy(this.tengjiaProxyFactory)
        }

        super.onDrop()
    }

    info(): string {
        return "藤甲"
    }
}

